package com.example.myapplication.flow

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.orhanobut.logger.Logger
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch

/**
 * 类描述: https://www.jianshu.com/p/fe1293e8f15c
 * 创建人:   tangchao$
 * 创建时间: 2021/8/27$ 8:47 AM$
 * 联系方式: 419704299@qq.com
 * 修改人:   tangchao$
 * 修改时间: 2021/8/27$ 8:47 AM$
 * 修改备注:  [说明本次修改内容]
 */
class FlowViewModel : ViewModel() {
    var uilivedata = MutableLiveData<String>()

    val sharedFlow = MutableSharedFlow<String>()
    fun a3() {
        viewModelScope.launch {
            sharedFlow.emit("hello")
            sharedFlow.emit("shareflow")

        }
    }

    fun login() {
        viewModelScope.launch {
            var fl = loginFlow("name", "password")
//            fl.map {
//                it + "MAP"
//            }.collect {
//                Logger.d("FlowViewModel===login: " + it);
//                uilivedata.value(it)
//            }
//            fl.toList().forEach {
//                uilivedata.value = it
//            }
            var aa = fl.toList().get(0)
            Logger.d("FlowViewModel===login: aa" + aa);
            uilivedata.value = aa.toString()


        }
    }

    private suspend fun loginFlow(s: String, s1: String) = flow<String> {
        emit("1")
        Logger.d("FlowViewModel===loginFlow: 1");
        throw RuntimeException()
    }.onStart {
        emit("onstart")
        Logger.d("FlowViewModel===loginFlow: 2");
    }.onCompletion { value ->
        if (value != null) {//有异常情况
            Logger.d("FlowViewModel===loginFlow: 异常");
        } else
            emit("111")
        Logger.d("FlowViewModel===loginFlow: 3");

    }.flowOn(Dispatchers.IO).catch { emit("catch") }
//    如果把 onCompletion、catch 交换一下位置，则 catch 操作符捕获到异常后，不会影响到下游


    suspend fun t1(): Unit {
        flow {
            for (i in 1..5) {
                kotlinx.coroutines.delay(100)
                emit(i)

            }
        }.collect {
            Logger.d("FlowViewModel===t1: " + it);
        }

        flowOf(1, 2, 3).onEach {
            delay(100)
        }.collect {
            Logger.d("FlowViewModel===t1: " + it);

        }

        listOf(1, 2, 3).asFlow().onEach {
            delay(100)
        }.collect {
            Logger.d("FlowViewModel===t1: " + it);
        }

        channelFlow {
            for (i in 1..3) {
                delay(100)
                send(i)
            }
        }.collect {
            Logger.d("FlowViewModel===t1: " + it);
        }

    }

    suspend fun t2(): Unit {
        (1..5).asFlow().onEach {
            if (it == 3) throw RuntimeException("$it")
        }.retry(2) {
            if (it is RuntimeException) {
                return@retry true
            }
            false
        }.onEach {
            Logger.d("FlowViewModel===t2: " + it);

        }.catch {
            Logger.e("===: " + it.printStackTrace());

        }.collect {
            Logger.d("===: ");

        }

    }

}